package org.singledog.form.builder.parser.freemarker.view;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.singledog.form.builder.MagicConstants;
import org.singledog.form.builder.parser.freemarker.EasyUIConstants;
import org.singledog.form.builder.parser.freemarker.freemarker.FreeMarkerConfiguration;
import org.singledog.form.builder.util.JsonUtil;
import org.singledog.form.builder.view.AbstractView;
import org.singledog.form.builder.view.ViewInterceptor;
import org.springframework.util.CollectionUtils;

import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.Map;

@Slf4j
public abstract class AbstractFreemarkerView extends AbstractView implements EasyUIConstants {

    public AbstractFreemarkerView(String viewCode, JSONObject schema) {
        super(viewCode, schema);
    }

    protected String getTemplateName() {
        return this.viewType().name().toLowerCase().concat(".ftl");
    }

    protected String addDataOptions(String dataOptions, Map<String, Object> appendingMap) {
        if (CollectionUtils.isEmpty(appendingMap)) {
            return dataOptions;
        }

        StringBuilder options = new StringBuilder();
        if (!StringUtils.isEmpty(dataOptions)) {
            options.append(dataOptions);
        } else {
            options.append("viewCode: '").append(viewCode).append("'");
        }

        for (Map.Entry<String, Object> entry : appendingMap.entrySet()) {
            options.append(DATA_OPTION_SEPARATOR)
                    .append(entry.getKey()).append(DATA_OPTION_KV_SEPARATOR).append(getDataOptionValue(entry.getValue()));
        }

        return options.toString();
    }

    protected String getDataOptionValue(Object obj) {
        if (obj == null) {
            return "''";
        }

        if (obj instanceof CharSequence) {
            return "'" + obj + "'";
        }

        if ((obj instanceof Number) || (obj instanceof Boolean)) {
            return String.valueOf(obj);
        }

        return JSON.toJSONString(obj);
    }

    @Override
    public String toHtml(ViewInterceptor customizer, Map<String, Object> viewData, boolean readonly) {

        viewData = processTemplateData(viewData, readonly);

        if (customizer != null) {
            customizer.beforeRender(viewData, readonly);
        }

        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
             OutputStreamWriter osw = new OutputStreamWriter(byteArrayOutputStream, StandardCharsets.UTF_8)){
            FreeMarkerConfiguration.getTemplate(getFullyTemplateName()).process(viewData, osw);
            return byteArrayOutputStream.toString();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return null;
    }

    protected Map<String, Object> processTemplateData(Map<String, Object> viewData, boolean readonly) {
        JSONObject ret = new JSONObject();
        String code = getViewCode();
        if (!StringUtils.isEmpty(code)) {
            code = StringUtils.replace(code, "-", "_");
        }
        ret.put(MagicConstants.VIEW_CODE, code);
        ret.put(MagicConstants.READONLY, readonly);
        ret.putAll(schema);

        //合并JSON
        if (!CollectionUtils.isEmpty(viewData)) {
            JsonUtil.mergeJson(ret, viewData);
        }

        return ret;
    }

    private String getFullyTemplateName() {
        return "easyui/".concat(getTemplateName());
    }
}
